home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / circuits / irsim-ca.2 / irsim-ca / irsim-cap-9.2 / src / irsim / eval.c < prev    next >
C/C++ Source or Header  |  1995-05-26  |  15KB  |  589 lines

  1. /* 
  2.  *     ********************************************************************* 
  3.  *     * Copyright (C) 1988, 1990 Stanford University.                     * 
  4.  *     * Permission to use, copy, modify, and distribute this              * 
  5.  *     * software and its documentation for any purpose and without        * 
  6.  *     * fee is hereby granted, provided that the above copyright          * 
  7.  *     * notice appear in all copies.  Stanford University                 * 
  8.  *     * makes no representations about the suitability of this            * 
  9.  *     * software for any purpose.  It is provided "as is" without         * 
  10.  *     * express or implied warranty.  Export of this software outside     * 
  11.  *     * of the United States of America may require an export license.    * 
  12.  *     ********************************************************************* 
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include "defs.h"
  17. #include "net.h"
  18. #include "globals.h"
  19.  
  20.  
  21. /*
  22.  * simulator can use one of several models, selectable by the user.  Which
  23.  * model to use is kept as index into various dispatch tables, all defined
  24.  * below.
  25.  */
  26. public
  27. #define    LIN_MODEL    0
  28. public
  29. #define    SWT_MODEL    1
  30. public
  31. #define    NMODEL        2        /* number of models supported */
  32.  
  33.  
  34. public void (*model_table[NMODEL])() =    /* model dispatch table */
  35.   {
  36.     linear_model, switch_model
  37.   };
  38.  
  39.  
  40. public    int    model_num = LIN_MODEL;        /* index of model in table */
  41. public    void    (*model)() = linear_model;    /* evaluation model */
  42. public    int    sm_stat = NORM_SIM;        /* simulation status */
  43. public    int    treport = 0;            /* report format */
  44.  
  45. private    int    firstcall = 1;        /* reset when calling init_vdd_gnd */
  46. private    struct Node nd_no_inp;
  47.  
  48. extern FILE    *caplogfile;
  49. extern float    totpower;
  50.  
  51.  
  52. /*
  53.  * find transistors with gates of VDD or GND and calculate values for source
  54.  * and drain nodes just in case event driven calculations don't get to them.
  55.  */
  56. private void init_vdd_gnd()
  57.   {
  58.     enqueue_input( VDD_node, HIGH );
  59.     enqueue_input( GND_node, LOW );
  60.  
  61.     firstcall = 0;        /* initialization now taken care of */
  62.   }
  63.  
  64. /*
  65.  * Reset the firstcall flag.  Usually after reading history dump or net state
  66.  */
  67. public void NoInit()
  68.   {
  69.     firstcall = 0;
  70.   }
  71.  
  72.  
  73. /*
  74.  * Set the firstcall flags.  Used when moving back to time 0.
  75.  */
  76. public void ReInit()
  77.   {
  78.     firstcall = 1;
  79.   }
  80.  
  81. /*
  82.  * Print decay event.
  83.  */
  84. private void pr_decay( e )
  85.   evptr  e;
  86.   {
  87.     nptr  n = e->enode;
  88.  
  89.     lprintf( stdout, " @ %.1fns %s: decay %c -> X\n",
  90.       d2ns( e->ntime ), pnode( n ), vchars[ n->npot ] );
  91.   }
  92.  
  93.  
  94. /*
  95.  * Print watched node event.
  96.  */
  97. private void pr_watched( e, n )
  98.   evptr  e;
  99.   nptr   n;
  100.   {
  101.     int   tmp;
  102.  
  103.     if( n->nflags & INPUT )
  104.       {
  105.     lprintf( stdout, " @ %.1fns input %s: -> %c\n",
  106.       d2ns( e->ntime ), pnode( n ), vchars[ e->eval ] );
  107.     return;
  108.       }
  109.  
  110.     tmp = (debug & DEBUG_EV) ? (REPORT_TAU | REPORT_DELAY) : treport;
  111.  
  112.     lprintf( stdout, " @ %.1fns %s: %c -> %c",
  113.       d2ns( e->ntime ), pnode( n ), vchars[ n->npot ], vchars[ e->eval ] );
  114.  
  115.     switch( tmp & (REPORT_TAU | REPORT_DELAY | REPORT_CAP) )
  116.       {
  117.     case 0 :
  118.         lprintf( stdout, "\n" );                    break;
  119.     case REPORT_TAU :
  120.         lprintf( stdout, " (tau=%.1fns)\n", d2ns( e->rtime ) );    break;
  121.     case REPORT_DELAY :
  122.         lprintf( stdout, " (delay=%.1fns)\n", d2ns( e->delay ) );    break;
  123.     case REPORT_CAP :
  124.         if ( caplogfile != NULL )
  125.         {
  126.         fprintf( caplogfile,"%.1f %s: %c -> %c",
  127.               d2ns( e->ntime ), pnode( n ), vchars[ n->npot ],
  128.               vchars[ e->eval ] );
  129.         fprintf( caplogfile, " %.1f, %.1f, %4.3f)\n",
  130.                 d2ns( e->rtime ), d2ns( e->delay ), n->ncap );
  131.         }
  132.         break;
  133.     default :
  134.         lprintf( stdout, " (tau=%.1fns, delay=%.1fns, cap=%4.3fpf)\n",
  135.           d2ns( e->rtime ), d2ns( e->delay ), n->ncap );
  136.       }
  137.   }
  138.  
  139. /*
  140.  * Keep track of node transitions for both INPUT and non-INPUT nodes
  141.  * except for POWER_RAIL nodes (PEL 5/31/93).
  142.  */
  143. private void count_transitions( n, oldval, newval )
  144.   nptr n;
  145.   int oldval, newval;
  146.   {
  147.     /* Count non-INPUT and INPUT transitions (PEL 4/20/93) */
  148.     if( ( not (n->nflags & INPUT) ) ||
  149.         ( not (n->nflags & POWER_RAIL) && count_InTrans ) )
  150.       {
  151.     if( oldval != newval )
  152.       {
  153.         n->trans++;
  154.         totpower += n->ncap;
  155.         /* count 0->1 transitions (PEL 5/3/93) */
  156.         if     ( oldval==LOW  && newval==HIGH ) n->trans01++;
  157.         else if( oldval!=HIGH && newval==HIGH ) n->trans01+=0.5;
  158.         else if( oldval==LOW  && newval!=LOW  ) n->trans01+=0.5;
  159.       }
  160.       }
  161.   }
  162.  
  163. /*
  164.  * Print capwatched node event.
  165.  */
  166. private void pr_capwatched( e, n )
  167.   evptr  e;
  168.   nptr   n;
  169.   {
  170.     int   tmp;
  171.  
  172.     /*
  173.      * Moved all trans. accounting to before caplogfile check (PEL 5/12/93)
  174.      * Also, count_transitions() won't count INPUT transitions since
  175.      * n->npot==e->eval here.  INPUT transitions get counted in SetInputs().
  176.      * (PEL 5/31/93)
  177.      */
  178.     if( not (n->nflags & INPUT) ) count_transitions( n, n->npot, e->eval );
  179.  
  180.     if( caplogfile == NULL ) 
  181.       return;
  182.  
  183.     if( n->nflags & INPUT )
  184.       {
  185.     fprintf( caplogfile, "%.1f *INPUT* %s -> %c\t",
  186.       d2ns( e->ntime ), pnode( n ), vchars[ e->eval ] );
  187.     fprintf( caplogfile, "%.1f %.1f %4.3f\n",
  188.       d2ns( e->rtime ), d2ns( e->delay ), n->ncap );
  189.     return;
  190.       }
  191.  
  192.     fprintf( caplogfile,"%.1f\t%s\t%c -> %c\t",
  193.       d2ns( e->ntime ), pnode( n ), vchars[ n->npot ], vchars[ e->eval ] );
  194.     fprintf( caplogfile, "%.1f %.1f %4.3f\n",
  195.         d2ns( e->rtime ), d2ns( e->delay ), n->ncap );
  196.   }
  197.  
  198.  
  199. /*
  200.  * Run through the event list, marking all nodes that need to be evaluated.
  201.  */
  202. private void MarkNodes( evlist )
  203.   evptr  evlist;
  204.   {
  205.     register nptr   n;
  206.     register tptr   t;
  207.     register lptr   l;
  208.     register evptr  e = evlist;
  209.     long            all_flags = 0;
  210.                     
  211.     do
  212.       {
  213.     n = e->enode;
  214.  
  215.     all_flags |= n->nflags;
  216.  
  217.     if( e->type == DECAY_EV and ( (treport & REPORT_DECAY) or
  218.       (n->nflags & (WATCHED | STOPONCHANGE)) ) )
  219.         pr_decay( e );
  220.     else if( n->nflags & (WATCHED | STOPONCHANGE) )
  221.         pr_watched( e, n );
  222.     else if( n->nflags & (CAPWATCHED | STOPONCHANGE) )
  223.         pr_capwatched( e, n );
  224.  
  225.     n->npot = e->eval;
  226.  
  227.         /* Add the new value to the history list (if they differ) */
  228.     if( not (n->nflags & INPUT) and (n->curr->val != n->npot) )
  229.         AddHist( n, n->npot, 0, (long) e->ntime, (long) e->delay,
  230.           (long) e->rtime );
  231.  
  232. #ifdef STATS
  233.     { extern int ev_hgm; if( ev_hgm ) IncHistEvCnt( -1 ); }
  234. #endif STATS
  235.  
  236.         /* for each transistor controlled by event node, mark 
  237.          * source and drain nodes as needing recomputation.
  238.          *
  239.          * Added MOSSIMs speed up by first checking if the 
  240.          * node needs to be rechecked  mh
  241.          *
  242.          * Fixed it so nodes with pending events also get
  243.          * re_evaluated. Kevin Karplus
  244.          */
  245.     for( l = n->ngate; l != NULL; l = l->next )
  246.       {
  247. #ifdef notdef
  248.         char  oldstate;
  249.  
  250.         t = l->xtor;
  251.         /*
  252.          * Some of these optimizations only work right when the
  253.          * stage at the src/drn contains no loops.  For example,
  254.          * when a transistor turns off and the src=1 and drn=0,
  255.          * the transistor may break a previous loop causing the
  256.          * src or drn to change value.
  257.          * 
  258.          * Also, while the state of the src/drn of the transistor
  259.          * in question may not change state, the current through
  260.          * their stage is altered; this current change may change
  261.          * the state of other nodes in the stage, so they better
  262.          * be avaluated.  These optimizations work best in MOSSIM
  263.          * since that model does not account for the current through
  264.          * the stage.    A.S.
  265.          */
  266.         oldstate = t->state;
  267.  
  268.         t->state = compute_trans_state( t );
  269.         if( (t->drain->npot == X) or (t->source->npot == X) or
  270.           ((t->drain->npot != t->source->npot) and
  271.           (t->state == ON)) or
  272.           ((t->drain->npot == t->source->npot) and
  273.           (t->state == OFF)) or
  274.           ((t->state == UNKNOWN) and
  275.           not (oldstate == OFF and
  276.           (t->drain->npot == t->source->npot))) or
  277.           (t->drain->events != NULL) or
  278.           (t->source->events != NULL) )
  279.           {
  280.         if( not (t->source->nflags & INPUT) )
  281.             t->source->nflags |= VISITED;
  282.         if( not (t->drain->nflags & INPUT) )
  283.             t->drain->nflags |= VISITED;
  284.           }
  285. #else
  286.         t = l->xtor;
  287.         t->state = compute_trans_state( t );
  288.         if( not (t->source->nflags & INPUT) )
  289.         t->source->nflags |= VISITED;
  290.         if( not (t->drain->nflags & INPUT) )
  291.         t->drain->nflags |= VISITED;
  292. #endif
  293.       }
  294.     free_from_node( e, n );    /* remove to avoid punting this event */
  295.     e = e->flink;
  296.       }
  297.     while( e != NULL );
  298.  
  299.     /* run thorugh event list again, marking src/drn of input nodes */
  300.     if( all_flags & INPUT )
  301.       {
  302.     for( e = evlist; e != NULL; e = e->flink )
  303.       {
  304.         n = e->enode;
  305.  
  306.         if( (n->nflags & (INPUT | POWER_RAIL)) != INPUT )
  307.         continue;
  308.         
  309.         for( l = n->nterm; l != NULL; l = l->next )
  310.           {
  311.         t = l->xtor;
  312.         if( t->state != OFF )
  313.           {
  314.             register nptr other = other_node( t, n );
  315.             if( not( other->nflags & (INPUT | VISITED) ) )
  316.             other->nflags |= VISITED;
  317.           }
  318.           }
  319.       }
  320.       }
  321.   }
  322.  
  323.  
  324. private long EvalNodes( evlist )
  325.   evptr  evlist;
  326.   {
  327.     register tptr   t;
  328.     register lptr   l;
  329.     register nptr   n;
  330.     register evptr  event = evlist;
  331.     long            brk_flag = 0;
  332.  
  333.     do
  334.       {
  335.     nevent += 1;        /* advance counter to that of this event */
  336.     n = cur_node = event->enode;
  337.     n->c.time = event->ntime;    /* set up the cause stuff */
  338.     n->t.cause = event->p.cause;
  339.  
  340.     npending -= 1;
  341.  
  342.       /* now calculate new value for each marked node.  Some nodes marked
  343.        * above may become unmarked by earlier calculations before we get
  344.        * to them in this loop...
  345.        */
  346.  
  347.     for( l = n->ngate; l != NULL; l = l->next )
  348.       {
  349.         t = l->xtor;
  350.         if( t->source->nflags & VISITED )
  351.         (*model)( t->source );
  352.         if( t->drain->nflags & VISITED )
  353.         (*model)( t->drain );
  354.       }
  355.  
  356.     if( (n->nflags & (INPUT | POWER_RAIL)) == INPUT )
  357.       {
  358.         for( l = n->nterm; l != NULL; l = l->next )
  359.           {
  360.         nptr  other;
  361.  
  362.         t = l->xtor;
  363.         other = other_node( t, n );
  364.         if( other->nflags & VISITED )
  365.             (*model)( other );
  366.           }
  367.       }
  368.  
  369.         /* see if we want to halt if this node changes value */
  370.     brk_flag |= n->nflags;
  371.  
  372.     event = event->flink;
  373.       }
  374.     while( event != NULL );
  375.  
  376.     return( brk_flag );
  377.   }
  378.  
  379.  
  380. /*
  381.  * Change the state of the nodes in the given input list to their new value,
  382.  * setting their INPUT flag and enqueueing the event.
  383.  */
  384. private void SetInputs( listp, val )
  385.   register iptr  *listp;
  386.   register int   val;
  387.   {
  388.     register nptr  n, other;
  389.     register lptr  l;
  390.     register tptr  t;
  391.     iptr           ip, last;
  392.  
  393.     for( ip = last = *listp; ip != NULL; ip = ip->next )
  394.       {
  395.     last = ip;
  396.  
  397.     n = ip->inode;
  398.  
  399.     /* Set INPUT flag before counting transitions (PEL 7/21/93) */
  400.     n->nflags &= ~INPUT_MASK;
  401.     n->nflags |= INPUT;
  402.  
  403.     /* Count INPUT transitions (PEL 5/31/93) */
  404.     count_transitions( n, n->npot, val );
  405.  
  406.     n->npot = val;
  407.  
  408.  
  409.         /* enqueue event so consequences are computed. */
  410.     enqueue_input( n, val );
  411.  
  412.     if( n->curr->val != val or not (n->curr->inp) )
  413.         AddHist( n, val, 1, cur_delta, 0L, 0L );
  414.       }
  415.  
  416.     if( last )
  417.       {
  418.     last->next = infree;
  419.     infree = *listp;
  420.       }
  421.     *listp = NULL;
  422.   }
  423.  
  424.  
  425. private void MarkNOinputs()
  426.   {
  427.     register iptr  list;
  428.  
  429.     for( list = xinputs; list != NULL; list = list->next )
  430.       {
  431.     list->inode->nflags &= ~(INPUT_MASK | INPUT);
  432.     list->inode->nflags |= VISITED;
  433.       }
  434.   }
  435.  
  436.  
  437.     /* nodes which are no longer inputs */
  438. private void EvalNOinputs()
  439.   {
  440.     nptr  n;
  441.     iptr  list, last;
  442.  
  443.     for( list = last = xinputs; list != NULL; list = list->next )
  444.       {
  445.     cur_node = n = list->inode;
  446.     AddHist( n, (int) n->curr->val, 0, cur_delta, 0L, 0L );
  447.     if( n->nflags & VISITED )
  448.         (*model)( n );
  449.     last = list;
  450.       }
  451.     if( last )
  452.       {
  453.     last->next = infree;
  454.     infree = xinputs;
  455.       }
  456.     xinputs = NULL;
  457.   }
  458.  
  459.  
  460. public int step( stop_time )
  461.   long  stop_time;
  462.   {
  463.     evptr  evlist;
  464.     long   brk_flag;
  465.     int    ret_code = 0;
  466.  
  467.     /* look through input lists updating any nodes which just become inputs */
  468.  
  469.     MarkNOinputs();            /* nodes no longer inputs */
  470.     SetInputs( &hinputs, HIGH );    /* HIGH inputs */
  471.     SetInputs( &linputs, LOW );        /* LOW inputs */
  472.     SetInputs( &uinputs, X );        /* X inputs */
  473.  
  474.     /* 
  475.      * On the first call to step, make sure transistors with gates
  476.      * of vdd and gnd are set up correctly.  Mark initial inputs first!
  477.      */
  478.     if( firstcall )
  479.     init_vdd_gnd();
  480.  
  481.   try_again :
  482.     /* process events until we reach specified stop time or events run out. */
  483.     while( (evlist = get_next_event( stop_time )) != NULL )
  484.       {
  485.     MarkNodes( evlist );
  486.     if( xinputs ) EvalNOinputs();
  487.  
  488.     brk_flag = EvalNodes( evlist );
  489.  
  490.     FreeEventList( evlist );    /* return event list to free pool */
  491.  
  492.     if( int_received )
  493.         goto done;
  494.     if( brk_flag & (WATCHVECTOR | STOPONCHANGE | STOPVECCHANGE) )
  495.       {
  496.         if( brk_flag & (WATCHVECTOR | STOPVECCHANGE) )
  497.         disp_watch_vec( brk_flag );
  498.         if( brk_flag & (STOPONCHANGE | STOPVECCHANGE) )
  499.           {
  500.         ret_code = 1;
  501.         goto done;
  502.           }
  503.       }
  504.       }
  505.  
  506.     if( xinputs )
  507.       {
  508.     EvalNOinputs();
  509.     goto try_again;
  510.       }
  511.  
  512.     cur_delta = stop_time;
  513.   done :
  514.     if( analyzerON )
  515.     UpdateWindow( cur_delta );
  516.     return( ret_code );
  517.   }
  518.  
  519.  
  520. /* table to convert transistor type and gate node value into switch state
  521.  * indexed by switch_state[transistor-type][gate-node-value].
  522.  */
  523. public    char  switch_state[NTTYPES][4] = 
  524.   {
  525.     OFF,    UNKNOWN,    UNKNOWN,    ON,    /* NCHAH */
  526.     ON,        UNKNOWN,    UNKNOWN,    OFF,    /* PCHAN */
  527.     WEAK,    WEAK,        WEAK,        WEAK,   /* RESIST */
  528.     WEAK,    WEAK,        WEAK,        WEAK,   /* DEP */
  529.   };
  530.  
  531.  
  532. /* compute state of transistor.  If gate is a simple node, state is determined
  533.  * by type of implant and value of node.  If gate is a list of nodes, then
  534.  * this transistor represents a stack of transistors in the original network,
  535.  * and we perform the logical AND of all the gate node values to see if
  536.  * transistor is on.
  537.  */
  538. public
  539. #define     compute_trans_state( TRANS )                    \
  540.     ( ((TRANS)->ttype & GATELIST) ?                    \
  541.     ComputeTransState( TRANS ):                    \
  542.     switch_state[ BASETYPE( (TRANS)->ttype ) ][ (TRANS)->gate->npot ] )
  543.  
  544.  
  545. public int ComputeTransState( t )
  546.   register tptr  t;
  547.   {
  548.     register nptr  n;
  549.     register tptr  l;
  550.     register int   result;
  551.  
  552.     switch( BASETYPE( t->ttype ) )
  553.       {
  554.     case NCHAN :
  555.         result = ON;
  556.         for( l = (tptr) t->gate; l != NULL; l = l->scache.t )
  557.           {
  558.         n = l->gate;
  559.         if( n->npot == LOW )
  560.             return( OFF );
  561.         else if( n->npot == X )
  562.             result = UNKNOWN;
  563.           }
  564.         return( result );
  565.  
  566.     case PCHAN :
  567.         result = ON;
  568.         for( l = (tptr) t->gate; l != NULL; l = l->scache.t )
  569.           {
  570.         n = l->gate;
  571.         if( n->npot == HIGH )
  572.             return( OFF );
  573.         else if( n->npot == X )
  574.             result = UNKNOWN;
  575.           }
  576.         return( result );
  577.  
  578.     case DEP :
  579.     case RESIST :
  580.         return( WEAK );
  581.  
  582.     default :
  583.         lprintf( stderr,
  584.           "**** internal error: unrecongized transistor type (0x%x)\n",
  585.           BASETYPE( t->ttype ) );
  586.         return( UNKNOWN );
  587.       }
  588.   }
  589.